package casbinx

import (
	"context"
	"time"

	"gitee.com/chunanyong/zorm"
	"gitee.com/workits/pkgs/cachex"
	"github.com/casbin/casbin/v2"
	"github.com/casbin/casbin/v2/model"
	zormadapter "github.com/workits/casbin-zorm-adapter"
)

var enforcer *casbin.SyncedCachedEnforcer

// Enable 开启并初始化casbin
func Enable(ctx context.Context, cfg Config, dbDao *zorm.DBDao) {
	// 防止重复初始化
	if enforcer != nil {
		return
	}

	// 初始化model
	m, err := model.NewModelFromString(cfg.RbacRule)
	if err != nil {
		panic(err)
	}

	// 检测casbin rule表是否存在，不存在创建
	if err := InitDB(cfg, dbDao); err != nil {
		panic(err)
	}

	// 初始化adapter
	a, err := zormadapter.NewAdapterWithContext(ctx, dbDao, cfg.CasbinRuleTable)
	if err != nil {
		panic(err)
	}

	// 实例化缓存策略
	if enforcer, err = casbin.NewSyncedCachedEnforcer(m, a); err != nil {
		panic(err)
	}
	enforcer.EnableLog(false)                   // 关闭casbin自带logger
	enforcer.SetCache(NewCasbinCache(cachex.C)) // 配置自定义缓存
	enforcer.SetExpireTime(30 * time.Minute)    // 设置失效时间
}

// Enforce 验证
func Enforce(rvals ...any) (bool, error) {
	return enforcer.Enforce(rvals...)
}

// AddPolicy 添加权限
func AddPolicy(sub, obj, act string) error {
	_, err := enforcer.AddPolicy(sub, obj, act)
	return err
}

// RemoveFilteredPolicy 根据条件删除权限
// 例如：
// RemoveFilteredPolicy(0, "role")           // 根据角色删除
// RemoveFilteredPolicy(1, "path")           // 根据接口地址删除
// RemoveFilteredPolicy(1, "path", "method") // 根据接口地址和请求方式删除
// RemoveFilteredPolicy(2, "method")         // 根据请求方式删除
func RemoveFilteredPolicy(fIdx int, fval ...string) error {
	_, err := enforcer.RemoveFilteredPolicy(fIdx, fval...)
	return err
}
